

#include "time/su_timeUtil.h"
#include "time/su_timestamp.h"
#include "time/su_timer.h"
#include "su_include.h"

#include   <stdio.h>      
#include   <stdio.h>      
#include   <time.h>   
#include <cstring>
#include "unit_test.h"


//#ifdef   WIN32      
//#define   LOCALTIME_R(t)     localtime((t))      
//#else      
//#define   LOCALTIME_R(t)     localtime_r((t),   (struct   tm   *)&tmres)      
//#endif   

#define _CRT_SECURE_NO_WARNINGS

using namespace std;
using namespace su;
namespace
{

void currentTime()     
{       
	{
		time_t long_time = 0;
		tm   tmNow;
		localtime_r(&long_time, &tmNow);
		UNIT_INFO("timestamp 0  转本地日期:  %d年%d月%d日   %d时%d分%d秒 周%d", tmNow.tm_year, tmNow.tm_mon + 1, tmNow.tm_mday, tmNow.tm_hour, tmNow.tm_min, tmNow.tm_sec
			, tmNow.tm_wday
		);
		// 70年1月1日   8时0分0秒
	} 
	{
		time_t long_time = 0;
		tm   tmNow;
		tmNow = *gmtime(&long_time);
		UNIT_INFO("timestamp 0  转utc日期:  %d年%d月%d日   %d时%d分%d秒 周%d", tmNow.tm_year, tmNow.tm_mon + 1, tmNow.tm_mday, tmNow.tm_hour, tmNow.tm_min, tmNow.tm_sec
			, tmNow.tm_wday
		);
		//70年1月1日   0时0分0秒
	}
	{
		time_t long_time = 0;
		time(&long_time);
		tm   tmNow;
		localtime_r(&long_time, &tmNow);
		UNIT_INFO("cur localtime_r	%d年%d月%d日   %d时%d分%d秒 周%d", tmNow.tm_year, tmNow.tm_mon + 1, tmNow.tm_mday, tmNow.tm_hour, tmNow.tm_min, tmNow.tm_sec
			, tmNow.tm_wday
		);
	}
	{

		struct timespec sp;
		clock_gettime(CLOCK_REALTIME, &sp);


		time_t long_time = sp.tv_sec;
		tm   tmNow;
		localtime_r(&long_time, &tmNow);
		UNIT_INFO("cur clock_gettime %d年%d月%d日   %d时%d分%d秒 周%d", tmNow.tm_year, tmNow.tm_mon + 1, tmNow.tm_mday, tmNow.tm_hour, tmNow.tm_min, tmNow.tm_sec
			, tmNow.tm_wday
		);
	}
	{//获取时区，+- 12*3600

		time_t utcSec = 0;
		time(&utcSec);
		struct tm curData;
		localtime_r((const time_t*)&utcSec, &curData);

		struct tm* pUtcData = gmtime(&utcSec);

		int32_t tmpHour = curData.tm_hour - pUtcData->tm_hour;

		if (tmpHour < -12)
		{
			tmpHour += 24;
		}
		else if (tmpHour > 12)
		{
			tmpHour -= 24;
		}

		UNIT_INFO("时区 utc %d", tmpHour);
	}
	{
		tm tmNow;
		tmNow.tm_sec = 0;
		tmNow.tm_min = 0;
		tmNow.tm_hour = 0;
		tmNow.tm_mday = 4;		//4 == week 0
		tmNow.tm_mon = 0;	//0 start
		tmNow.tm_year = 1970 - 1900;
		tmNow.tm_isdst = 0;
		time_t utcTs =  mktime(&tmNow);
		UNIT_INFO("mktime 1970-01-04 00:00:00  utcTs = %ld", utcTs);

	}
	return;     
}  

void testCurCycleNum()
{
	{	
		//1970,1,4， 0时0分0秒 
		CycleNum week1(3600*24*7, 3600*24*0);
		tm tmNow ;
		tmNow.tm_sec = 0;
		tmNow.tm_min = 0; 
		tmNow.tm_hour = 0; 
		tmNow.tm_mday = 4;		//4 == week 0
		tmNow.tm_mon = 0;	//0 start
		tmNow.tm_year = 1970-1900;
		tmNow.tm_isdst = 0 ;

		time_t ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==0);

		tmNow.tm_mday = 3;	
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==0);

		tmNow.tm_mday = 10;	 //week 6
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==0);

		tmNow.tm_sec = 59;
		tmNow.tm_min = 59; 
		tmNow.tm_hour = 23; 
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==0);

		tmNow.tm_sec = 0;
		tmNow.tm_min = 0;
		tmNow.tm_hour = 0;
		tmNow.tm_mday = 11;	 //week 0
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==1);
		tmNow.tm_mday = 18;	 //week 0
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==2);
		tmNow.tm_mday = 24;	 //week 0
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==2);
	}
	{	
		//1970,1,4， 0时0分0秒 ，周期分界为周一+10秒
		CycleNum week1(3600*24*7, 3600*24*1+10);
		tm tmNow ;
		tmNow.tm_sec = 0;
		tmNow.tm_min = 0; 
		tmNow.tm_hour = 0; 
		tmNow.tm_mday = 4;		//4 == week 0
		tmNow.tm_mon = 0;	//0 start
		tmNow.tm_year = 1970-1900;
		tmNow.tm_isdst = 0 ;

		time_t ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==0);

		tmNow.tm_mday = 3;	
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==0);

		tmNow.tm_mday = 12;	 //week 1
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==0);

		tmNow.tm_sec = 9;
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==0);

		tmNow.tm_sec = 10;
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==1);

		tmNow.tm_mday = 12;	 //week 1
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==1);
	
		tmNow.tm_mday = 19;	 //week 0
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==2);
	}
	{	
		//2014,7,x，  ，周期分界为周一+10秒
		CycleNum week1(3600*24*7, 3600*24*1+10);
		tm tmNow ;
		tmNow.tm_sec = 0;
		tmNow.tm_min = 0; 
		tmNow.tm_hour = 0; 
		tmNow.tm_mday = 27;		// week 0
		tmNow.tm_mon = 6;	//7 start
		tmNow.tm_year = 2014-1900;
		tmNow.tm_isdst = 0 ;


		tmNow.tm_mday = 28;		// week 1
		tmNow.tm_sec = 9;
		time_t zero = week1.Get(mktime( &tmNow  ));


		tmNow.tm_mday = 28;		// week 1
		tmNow.tm_sec = 10;
		time_t ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==zero+1);

		tmNow.tm_mday = 29;		// week 2
		 ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==zero+1);
		

		tmNow.tm_mday = 4;		// week 1
		tmNow.tm_mon = 7;	
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==zero+2);

		tmNow.tm_mday = 4;		// week 1
		tmNow.tm_mon = 7;	
		tmNow.tm_sec = 9;
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==zero+1);
	}
	
	{	
		//2014,7,x，  ，周期分界为周一+10秒
		CycleNum week1(3600*24,0);
		tm tmNow ;
		tmNow.tm_sec = 0;
		tmNow.tm_min = 0; 
		tmNow.tm_hour = 0; 
		tmNow.tm_mday = 27;		// week 0
		tmNow.tm_mon = 6;	//7 start
		tmNow.tm_year = 2014-1900;
		tmNow.tm_isdst = 0 ;


		tmNow.tm_mday = 28;		// week 1
		time_t zero = week1.Get(mktime( &tmNow  ));

		tmNow.tm_mday = 29;	
		time_t ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==zero+1);

		tmNow.tm_mday = 29;	
		tmNow.tm_sec = 59;
		tmNow.tm_min = 59; 
		tmNow.tm_hour = 23; 
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==zero+1);
	}
	{
		CycleNum week1(3600*24, 10);
		tm tmNow ;
		tmNow.tm_sec = 0;
		tmNow.tm_min = 0; 
		tmNow.tm_hour = 0; 
		tmNow.tm_mday = 27;		// week 0
		tmNow.tm_mon = 6;	//7 start
		tmNow.tm_year = 2014-1900;
		tmNow.tm_isdst = 0 ;


		tmNow.tm_mday = 28;		// week 1
		tmNow.tm_sec = 9;
		time_t zero = week1.Get(mktime( &tmNow  ));

		tmNow.tm_mday = 29;	
		time_t ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==zero+1);

		tmNow.tm_mday = 29;	
		tmNow.tm_sec = 10; 
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==zero+2);
	}
	{
		CycleNum week1(3600/2, 10);
		tm tmNow;
		tmNow.tm_sec = 0;
		tmNow.tm_min = 0; 
		tmNow.tm_hour = 0; 
		tmNow.tm_mday = 27;		// week 0
		tmNow.tm_mon = 6;	//7 start
		tmNow.tm_year = 2014-1900;
		tmNow.tm_isdst = -1 ; //夏令时


		tmNow.tm_sec = 10;
		tmNow.tm_min = 0; 
		tmNow.tm_hour = 0; 	
		
		time_t zero = week1.Get(mktime( &tmNow  ));

		tmNow.tm_sec = 10;
		tmNow.tm_min = 30; 
		tmNow.tm_hour = 0;
		time_t ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==zero+1);

		tmNow.tm_sec = 9;
		tmNow.tm_min = 30; 
		tmNow.tm_hour = 0; 
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==zero+0);

		tmNow.tm_sec = 10;
		tmNow.tm_min = 0; 
		tmNow.tm_hour = 1; 
		ret = week1.Get(mktime( &tmNow  ));
		UNIT_ASSERT(ret==zero+2);

	}
}

void testPeriodAccumulate()
{
    SysTime::Ins().SetTimeOffset(0);
	PeriodAccumulate obj(1,10); 
	UNIT_ASSERT(10 ==obj.currentNum());
	obj.costNum(10);
	UNIT_ASSERT(0 ==obj.currentNum());
	SysTime::Ins().AddTimerOffset(1);
	UNIT_ASSERT(1 ==obj.currentNum());
	obj.costNum(1);
	UNIT_ASSERT(0 ==obj.currentNum());
	obj.addExtNum(11);
	UNIT_ASSERT(11 ==obj.currentNum());
	SysTime::Ins().AddTimerOffset(1);
	UNIT_ASSERT(11 ==obj.currentNum());
	obj.setMaxNum(12);
	UNIT_ASSERT(11 ==obj.currentNum());
	SysTime::Ins().AddTimerOffset(1);
	UNIT_ASSERT(12 ==obj.currentNum());
	obj.addExtNum(1);
	UNIT_ASSERT(13 ==obj.currentNum());
	
	obj.costNum(100);
	obj.setMaxNum(10);
	UNIT_ASSERT(0 ==obj.currentNum());
	SysTime::Ins().AddTimerOffset(1);


}


void waitUtill1()
{
	UNUSED(waitUtill1);
	for (;;)//wait untill 1sec period over
	{
		time_t t;
		time(&t);
		if (t%2==1)
		{
			//Info(t);
			break;
		}
	}
}
void waitUtill2()
{
	UNUSED(waitUtill2);
	for (;;)//wait untill 2sec period over
	{
		time_t t;
		time(&t);
		if (t%2==0)
		{
		//	Info(t);
			break;
		}
	}
}
void testSysPeriodCD()
{
    SysTime::Ins().SetTimeOffset(0);
	CdDefault obj(2);
	
	UNIT_ASSERT(!obj.IsCD());

	obj.StartCD();
	UNIT_ASSERT(obj.IsCD());
	SysTime::Ins().AddTimerOffset(2);
	UNIT_ASSERT(!obj.IsCD());


	obj.StartCD();
	UNIT_ASSERT(obj.IsCD());

	obj.StartCD();
	UNIT_ASSERT(obj.IsCD());
	obj.ClearCD();
	UNIT_ASSERT(!obj.IsCD());

}

void testAccumulCDBase()
{
	class AccumulCD : public AccumulCDBase<time_t>
	{
	public:
		AccumulCD(const time_t &forceCdDist)
			:AccumulCDBase(forceCdDist)
		{
		}
		virtual time_t CurrentTick() const
		{
			return SysTime::Ins().Sec();
		}
	};
	
    {
        SysTime::Ins().SetTimeOffset(0);
		AccumulCD obj(4);
		UNIT_ASSERT(!obj.IsForceCD());
		UNIT_ASSERT(0 == obj.GetCD());
		obj.AddCD(1);
		UNIT_ASSERT(1 == obj.GetCD());
		obj.AddCD(1);
		UNIT_ASSERT(2 == obj.GetCD());
		obj.AddCD(2);
		UNIT_ASSERT(4 == obj.GetCD());
		UNIT_ASSERT(obj.IsForceCD());

        SysTime::Ins().AddTimerOffset(4);
		UNIT_ASSERT(!obj.IsForceCD());
		UNIT_ASSERT(0 == obj.GetCD());

		obj.AddCD(1);
		UNIT_ASSERT(1 == obj.GetCD());
		obj.ClearCD();
		UNIT_ASSERT(!obj.IsForceCD());
		UNIT_ASSERT(0 == obj.GetCD());
	}
	{
		AccumulCD obj(4);
		UNIT_ASSERT(!obj.IsForceCD());
		UNIT_ASSERT(0 == obj.GetCD());
		obj.AddCD(1);
		UNIT_ASSERT(1 == obj.GetCD());
		obj.AddCD(1);
		UNIT_ASSERT(2 == obj.GetCD());
		obj.AddCD(2);
		UNIT_ASSERT(4 == obj.GetCD());
		UNIT_ASSERT(obj.IsForceCD());
		obj.ClearCD();
		UNIT_ASSERT(!obj.IsForceCD());
		UNIT_ASSERT(0 == obj.GetCD());
	}
}

void testNormalCdBase()
{

	{
        SysTime::Ins().SetTimeOffset(0);
		CdDefault obj(2);

		UNIT_ASSERT(!obj.IsCD());
		obj.StartCD();
		UNIT_ASSERT(obj.IsCD());
        SysTime::Ins().AddTimerOffset(2);
		UNIT_ASSERT(!obj.IsCD());


		obj.StartCD();
		UNIT_ASSERT(obj.IsCD());
		obj.ClearCD();
		UNIT_ASSERT(!obj.IsCD());
	}


    {
        SysTime::Ins().SetTimeOffset(0);
		CdDefault obj(2);

		UNIT_ASSERT(!obj.IsCD());
		obj.StartCD();
		UNIT_ASSERT(obj.GetCountDownTime()>1);
		UNIT_ASSERT(obj.IsCD());
		obj.ChangePeriod(3);
		UNIT_ASSERT(obj.GetCountDownTime()>2);
		SysTime::Ins().AddTimerOffset(2);
		UNIT_ASSERT(obj.IsCD());
		SysTime::Ins().AddTimerOffset(1);
		UNIT_ASSERT(!obj.IsCD());

	}
}

void testNormalCdBase2()
{
    {
        SysTime::Ins().SetTimeOffset(0);
		CdDefault obj(2);

		UNIT_ASSERT(!obj.IsCD());
		obj.StartCD();
		UNIT_ASSERT(obj.IsCD());
        SysTime::Ins().AddTimerOffset(2);
		UNIT_ASSERT(!obj.IsCD());


		obj.StartCD();
		UNIT_ASSERT(obj.IsCD());
		obj.ClearCD();
		UNIT_ASSERT(!obj.IsCD());
	}


    {
        SysTime::Ins().SetTimeOffset(0);
		CdDefault obj(2);

		UNIT_ASSERT(!obj.IsCD());
		obj.StartCD();
		UNIT_ASSERT(obj.GetCountDownTime()>1);
		UNIT_ASSERT(obj.IsCD());
		obj.ChangePeriod(3);
		UNIT_ASSERT(obj.GetCountDownTime()>2);
        SysTime::Ins().AddTimerOffset(2);
		UNIT_ASSERT(obj.IsCD());
		SysTime::Ins().AddTimerOffset(1);
		UNIT_ASSERT(!obj.IsCD());

	}
}
void testTimertt()
{
    //低概率，在系统1秒分界点跑这个代码就会通不过
	TimerCnt obj;
    SysTime::Ins().ClearOffsetForTest();
    SysTime::Ins().SetTimeOffset(0);

	UNIT_ASSERT(0 == obj.peerCurrentTimer());
	obj.start();
	UNIT_ASSERT(0 == obj.peerCurrentTimer());
    SysTime::Ins().SetTimeOffset(1);
    UNIT_ASSERT(1 == obj.peerCurrentTimer());
    SysTime::Ins().SetTimeOffset(2);
    UNIT_ASSERT(2 == obj.peerCurrentTimer());
    SysTime::Ins().SetTimeOffset(5);
	obj.pause();
    UNIT_ASSERT(5 == obj.peerCurrentTimer());
    SysTime::Ins().SetTimeOffset(10);
	UNIT_ASSERT(5 == obj.peerCurrentTimer());
	obj.resume();
    UNIT_ASSERT(5 == obj.peerCurrentTimer());
    SysTime::Ins().SetTimeOffset(11);
	UNIT_ASSERT(6 == obj.peerCurrentTimer());
    SysTime::Ins().SetTimeOffset(12);
	UNIT_ASSERT(7 == obj.end());


}


	void testPeriodResetCnt()
	{
		SysTime::Ins().ClearOffsetForTest();
        SysTime::Ins().SetTimeOffset(0);
		//uint8 buf[100];
		//Memory out(buf, 100);
		//const Memory in(buf, 100);



		{//1个重置
			SysTime::Ins().ClearOffsetForTest();
			SysTime::Ins().SetTimeOffset(0);
            SysTime::Ins().SetTimeByStr("2043-05-31-0-0-0");//周日0时
       

            VecInt64 vec_limit;
            vec_limit.push_back(3600*24*0);
			CycleMoreReset obj(3600*24*7, vec_limit);

			time_t start = obj.GetCurCycleNum();
  
            SysTime::Ins().AddTimerOffset(3600*24*1); 
            UNIT_ASSERT(start == obj.GetCurCycleNum());
            SysTime::Ins().AddTimerOffset(3600*24*5); 
            UNIT_ASSERT(start == obj.GetCurCycleNum());
            UNIT_ASSERT("2043-06-06 00-00-00" == SysTime::Ins().GetTimeStr() || "2043-06-06 01-00-00" == SysTime::Ins().GetTimeStr());
            UNIT_ASSERT(6 == SysTime::Ins().CurTm().tm_wday);
			SysTime::Ins().AddTimerOffset(3600*24*1); //流逝一日
			UNIT_ASSERT(0 == SysTime::Ins().CurTm().tm_wday);
			UNIT_ASSERT(start+1 == obj.GetCurCycleNum());
			SysTime::Ins().AddTimerOffset(3600*24*7); //流逝一周
			UNIT_ASSERT(0 == SysTime::Ins().CurTm().tm_wday);
			UNIT_ASSERT(start+2 == obj.GetCurCycleNum());
        }
		{//2个重置
			SysTime::Ins().ClearOffsetForTest();
            SysTime::Ins().SetTimeOffset(0);
            SysTime::Ins().SetTimeByStr("2043-05-31-0-0-0");//周日0时
            VecInt64 vec_limit;
            vec_limit.push_back(3600*24*0);//周日
            vec_limit.push_back(3600*24*1);//周一
			CycleMoreReset obj(3600*24*7, vec_limit);
			time_t start = obj.GetCurCycleNum();

			SysTime::Ins().AddTimerOffset(3600*24*1); 
			UNIT_ASSERT(start+1 == obj.GetCurCycleNum());
			SysTime::Ins().AddTimerOffset(3600*24*5); 
			UNIT_ASSERT(start+1 == obj.GetCurCycleNum());
            UNIT_ASSERT("2043-06-06 00-00-00" == SysTime::Ins().GetTimeStr() || "2043-06-06 01-00-00" == SysTime::Ins().GetTimeStr());
            UNIT_ASSERT(6 == SysTime::Ins().CurTm().tm_wday);
			SysTime::Ins().AddTimerOffset(3600*24*1); //流逝一周
			UNIT_ASSERT(start+2 == obj.GetCurCycleNum());

			SysTime::Ins().AddTimerOffset(3600*24*1); 
			UNIT_ASSERT(1 == SysTime::Ins().CurTm().tm_wday);//周一
			UNIT_ASSERT(start+3 == obj.GetCurCycleNum());

			SysTime::Ins().AddTimerOffset(3600*24*7); 
			UNIT_ASSERT(1 == SysTime::Ins().CurTm().tm_wday);//周一
			UNIT_ASSERT(start+5 == obj.GetCurCycleNum());

        }
		{//3个重置
			SysTime::Ins().ClearOffsetForTest();
			SysTime::Ins().SetTimeOffset(0);
            SysTime::Ins().SetTimeByStr("2043-05-31-0-0-0");//周日0时
            VecInt64 vec_limit;
			vec_limit.push_back(3600*24*3);//周三
			vec_limit.push_back(3600*24*0);//周日
            vec_limit.push_back(3600*24*1);//周一
			CycleMoreReset obj(3600*24*7, vec_limit);
			time_t start = obj.GetCurCycleNum();

			SysTime::Ins().AddTimerOffset(3600*24*1); 
			UNIT_ASSERT(start+1 == obj.GetCurCycleNum());
			SysTime::Ins().AddTimerOffset(3600*24*5); 
			UNIT_ASSERT(start+2 == obj.GetCurCycleNum());
			UNIT_ASSERT("2043-06-06 00-00-00" == SysTime::Ins().GetTimeStr()|| "2043-06-06 01-00-00" == SysTime::Ins().GetTimeStr());
			UNIT_ASSERT(6 == SysTime::Ins().CurTm().tm_wday);
			SysTime::Ins().AddTimerOffset(3600*24*1); //流逝一周
			UNIT_ASSERT(start+3 == obj.GetCurCycleNum());

			SysTime::Ins().AddTimerOffset(3600*24*1); 
			UNIT_ASSERT(1 == SysTime::Ins().CurTm().tm_wday);//周一
			UNIT_ASSERT(start+4 == obj.GetCurCycleNum());
			SysTime::Ins().AddTimerOffset(3600*24*1); 
			UNIT_ASSERT(2 == SysTime::Ins().CurTm().tm_wday);//周二
			UNIT_ASSERT(start+4 == obj.GetCurCycleNum());
			SysTime::Ins().AddTimerOffset(3600*24*1); 
			UNIT_ASSERT(3== SysTime::Ins().CurTm().tm_wday);//周三
			UNIT_ASSERT(start+5 == obj.GetCurCycleNum());

			SysTime::Ins().AddTimerOffset(3600*24*7); 
			UNIT_ASSERT(3 == SysTime::Ins().CurTm().tm_wday);//周三
			UNIT_ASSERT(start+8 == obj.GetCurCycleNum());
        }
	}

	void test1()
	{
		time_t sec = CycleNum::START_SEC;
		UNIT_ASSERT(0 == CycleNum::GetPeriodNum(sec+1, CycleType::HOUR));
		UNIT_ASSERT(0 == CycleNum::GetPeriodNum(sec, CycleType::HOUR));
		UNIT_ASSERT(0 == CycleNum::GetPeriodNum(sec+3600-1, CycleType::HOUR));
		UNIT_ASSERT(1 == CycleNum::GetPeriodNum(sec + 3600, CycleType::HOUR));
	}

	void testCycleTimer()
	{
		TimeDriver::Ins().Clear();
		SysTime::Ins().ClearOffsetForTest();
		SysTime::Ins().SetTimeOffset(0);
		SysTime::Ins().SetTimeByStr("2043-05-31-0-0-0");//周日0时

		{
			time_t lastSec = 0;
			auto f = [&lastSec]() {
				if (lastSec != 0)
				{
					UNIT_ASSERT(lastSec + 2 == SysTime::Ins().Sec());
				}
				lastSec = SysTime::Ins().Sec();
				//UNIT_INFO("sec = %ld", lastSec);
			};
			CycleTimer ct;
			ct.Start((CycleType)2, f);

			for (int i = 0; i < 10; i++)
			{
				SysTime::Ins().AddTimerOffset(1);
				TimeDriver::Ins().CheckTimeOut();
				UNIT_ASSERT(1 == TimeDriver::Ins().GetTimeNum());
			}
			UNIT_ASSERT(lastSec != 0);
		}
		{
			time_t lastSec = 0;
			auto f = [&lastSec]() {
				if (lastSec != 0)
				{
					UNIT_ASSERT(lastSec + 2 == SysTime::Ins().Sec());
				}
				lastSec = SysTime::Ins().Sec();
				//UNIT_INFO("sec = %ld", lastSec);
			};
			CycleTimer ct;
			ct.Start((CycleType)2, f, 1);

			for (int i = 0; i < 10; i++)
			{
				SysTime::Ins().AddTimerOffset(1);
				TimeDriver::Ins().CheckTimeOut();
				UNIT_ASSERT(1 == TimeDriver::Ins().GetTimeNum());
			}
			UNIT_ASSERT(lastSec != 0);
		}
		{
			time_t lastSec = 0;
			auto f = [&lastSec]() {
				if (lastSec != 0)
				{
					UNIT_ASSERT(lastSec + 4 == SysTime::Ins().Sec());
				}
				lastSec = SysTime::Ins().Sec();
				//UNIT_INFO("sec = %ld", lastSec);
			};
			CycleTimer ct;
			ct.Start((CycleType)4, f, 2);

			for (int i = 0; i < 50; i++)
			{
				SysTime::Ins().AddTimerOffset(1);
				TimeDriver::Ins().CheckTimeOut();
				UNIT_ASSERT(1 == TimeDriver::Ins().GetTimeNum());
			}
			UNIT_ASSERT(lastSec != 0);
		}
	}
	void testCheckSpanInCycle()
	{
		{
			CheckSpanInCycle t;
			//UNIT_ASSERT(!t.Init((CycleType)4, 0, 0));
			//UNIT_ASSERT(!t.Init((CycleType)4, 1, 0));
			//UNIT_ASSERT(!t.Init((CycleType)4, 1, 4));
			UNIT_ASSERT(t.Init((CycleType)4, 0, 1));
			UNIT_ASSERT(t.Init((CycleType)4, 1, 3));

		}

		{

			TimeDriver::Ins().Clear();
			SysTime::Ins().ClearOffsetForTest();
			SysTime::Ins().SetTimeOffset(0);
			SysTime::Ins().SetTimeByStr("2022-3-8-0-0-0", true);

			CheckSpanInCycle m;
			m.InitMonthType(1, 0, 2, 0);
			UNIT_ASSERT(!m.IsOpen());

			SysTime::Ins().SetTimeByStr("2022-1-1-0-0-0", true);
			UNIT_ASSERT(m.IsOpen());
			SysTime::Ins().SetTimeByStr("2022-1-2-0-0-0", true);
			UNIT_ASSERT(m.IsOpen());
			SysTime::Ins().SetTimeByStr("2022-1-2-0-0-1", true);
			UNIT_ASSERT(!m.IsOpen());
		} 
		{

			TimeDriver::Ins().Clear();
			SysTime::Ins().ClearOffsetForTest();
			SysTime::Ins().SetTimeOffset(0);
			SysTime::Ins().SetTimeByStr("2022-3-8-0-0-0", true);

			CheckSpanInCycle m;
			m.InitMonthType(1, 2, 2, 0);
			UNIT_ASSERT(!m.IsOpen());

			SysTime::Ins().SetTimeByStr("2022-1-1-0-0-0", true);
			UNIT_ASSERT(!m.IsOpen());
			SysTime::Ins().SetTimeByStr("2022-1-1-1-0-0", true);
			UNIT_ASSERT(m.IsOpen());
			SysTime::Ins().SetTimeByStr("2022-1-2-0-0-0", true);
			UNIT_ASSERT(m.IsOpen());
		}
	}

	//让某周期内时间段的 开始时刻 结束时刻 自动回调
	class MySpanInCycle : public SpanInCycle
	{
	public:
		int m_start = 0;
		int m_end = 0;
		virtual void OnStart() {
			m_start++; 
			//UNIT_INFO("start");
		};
		virtual void OnEnd() { 
			m_end++;
			//UNIT_INFO("end");
		};
	};

	void testSpanInCycle()
	{
		TimeDriver::Ins().Clear();
		SysTime::Ins().ClearOffsetForTest();
		SysTime::Ins().SetTimeOffset(0);


		MySpanInCycle t;
		//UNIT_ASSERT(!t.Init((CycleType)4, 0, 0));
		//UNIT_ASSERT(!t.Init((CycleType)4, 1, 0));
		//UNIT_ASSERT(!t.Init((CycleType)4, 1, 4));
		UNIT_ASSERT(t.Init((CycleType)4, 0, 1));
		UNIT_ASSERT(t.Init((CycleType)4, 1, 3, false));
		for (int i = 0; i < 20; i++)
		{
			SysTime::Ins().AddTimerOffset(1);
			TimeDriver::Ins().CheckTimeOut();
			UNIT_ASSERT(2 == TimeDriver::Ins().GetTimeNum());
			UNIT_ASSERT(t.m_start >= t.m_end);
		}
		UNIT_ASSERT(t.m_start>0);
		UNIT_ASSERT(t.m_end > 0);

		UNIT_ASSERT(t.Init((CycleType)4, 1, 3, true));
		for (int i = 0; i < 20; i++)
		{
			SysTime::Ins().AddTimerOffset(1);
			TimeDriver::Ins().CheckTimeOut();
			UNIT_ASSERT(2 == TimeDriver::Ins().GetTimeNum());
			UNIT_ASSERT(t.m_start >= t.m_end);
		}
		UNIT_ASSERT(t.m_start > 0);
		UNIT_ASSERT(t.m_end > 0);
	}
}//end namespace


UNITTEST(test_timeUtil)
{
	//test1();
	currentTime();
	//testCurCycleNum();
	//testSysPeriodCD();
	//testTimertt();
	//testPeriodResetCnt();

	//testPeriodAccumulate();
	//testAccumulCDBase();
	//testNormalCdBase();
	//testNormalCdBase2();

	//testCycleTimer();

	//testCheckSpanInCycle();
	//testSpanInCycle();
}